<script setup>
import { ref, reactive, onMounted, onUnmounted, nextTick } from "vue";
import * as THREE from "three";
import Stats from "three/examples/jsm/libs/stats.module.js";
import * as dat from "dat.gui";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import ChartBar from "@/components/ChartBar.vue";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import groundPng from "@/assets/img/ground.png";
import wallJpg from "@/assets/img/wall.jpg";

let scene;
let camera;
let renderer;
let controls;
let gui;

let w = ref(window.innerWidth);
let h = ref(window.innerHeight);

let keyboardState = reactive({});
let car = reactive({});

onMounted(() => {
  nextTick(() => {
    init();
    window.addEventListener("resize", handleResize);
  });
});

onUnmounted(() => {
  // 移除窗口大小变化的监听器
  window.removeEventListener("resize", handleResize);
  // 清理资源
  renderer.dispose();
  renderer.domElement.remove();
});

const init = () => {
  const container = document.getElementById("three-container");

  // 帧率器
  const stats = new Stats();
  container.appendChild(stats.dom);

  // GUI
  gui = new dat.GUI();

  // 创建场景
  scene = new THREE.Scene();

  // 创建相机
  camera = new THREE.PerspectiveCamera(75, w.value / h.value, 0.1, 1000);
  // 设置相机位置
  camera.position.z = 6;
  camera.position.y = 2;
  const cameraFolder = gui.addFolder("camera");
  cameraFolder.add(camera.position, "x", -10, 10, 0.1).name("相机x");
  cameraFolder.add(camera.position, "y", -10, 10, 0.1).name("相机y");
  cameraFolder.add(camera.position, "z", 0.1, 10, 0.1).name("相机z");

  // 创建渲染器
  renderer = new THREE.WebGLRenderer();
  renderer.setSize(w.value, h.value);
  container.appendChild(renderer.domElement);

  // 灯光
  const dLight = new THREE.DirectionalLight(0xffffff); // 方向光  太阳光

  dLight.position.set(1, 1, 1);
  const colors = {
    dLight: "#f56c6c",
  };
  const folderLight = gui.addFolder("Directional");
  folderLight.add(dLight, "intensity", 0, 1, 0.01).name("intensity"); //控制光线的强度或亮度
  folderLight.add(dLight.position, "x", -10, 10, 0.1).name("x方向");
  folderLight.add(dLight.position, "y", -10, 10, 0.1).name("y方向");
  folderLight.add(dLight.position, "z", -10, 10, 0.1).name("z方向");
  folderLight.addColor(colors, "dLight").onChange((color) => {
    dLight.color.set(color);
  });
  scene.add(dLight);
  // objects

  //   贴图
  const textureLoader = new THREE.CubeTextureLoader();
  const texture = textureLoader.load([
    "img/right.jpg", //右
    "img/left.jpg", //左
    "img/top.jpg", //上
    "img/bottom.jpg", //下
    "img/front.jpg", //前
    "/img/back.jpg", //后
  ]);
  //   scene.background = texture;
  scene.environment = texture; // 设置整个场景的环境贴图

  // 修改场景颜色
  scene.background = new THREE.Color("#d3d4d6");
  // 添加雾
  scene.fog = new THREE.Fog("#d3d4d6", 2, 10);

  // 导入模型
  // 东方之珠模型
  const gltfLoader = new GLTFLoader();
  gltfLoader.load("model/scene.gltf", (gltf) => {
    scene.add(gltf.scene);
  });

  // car
  gltfLoader.load("model/AngryEye.glb", (gltf) => {
    // gltf.scene.scale.set(0.5, 0.5, 0.5);
    // gltf.scene.position.y = -0.35;
    car = gltf.scene;
    car.rotation.y = -0.5 * Math.PI;
    car.scale.set(0.5, 0.5, 0.5);
    car.position.y = -0.35;
    scene.add(car);
    // 更新渲染
    renderer.render(scene, camera);
  });
  document.addEventListener("keydown", function (event) {
    keyboardState[event.keyCode] = true;
  });
  document.addEventListener("keyup", function (event) {
    keyboardState[event.keyCode] = false;
  });

  // 地
  const textureLoader2 = new THREE.TextureLoader();
  const textureGround = textureLoader2.load(groundPng);
  //  同上，在纹理中选择最近的像素
  textureGround.magFilter = THREE.NearestFilter;

  // 贴图 repeat 的使用
  textureGround.wrapS = THREE.RepeatWrapping; // x
  textureGround.wrapT = THREE.RepeatWrapping; // y
  textureGround.repeat.set(100, 100);

  const planeG = new THREE.PlaneGeometry(20, 10);
  const m = new THREE.MeshBasicMaterial({
    map: textureGround,
    side: THREE.DoubleSide,
  });
  const planeCube = new THREE.Mesh(planeG, m);
  planeCube.rotation.x = -0.5 * Math.PI;
  planeCube.position.y = -0.5;

  scene.add(planeCube);

  // 创建轨道控制器
  controls = new OrbitControls(camera, renderer.domElement);

  // 渲染循环
  const clock = new THREE.Clock();
  const animate = () => {
    const time = clock.getElapsedTime();

    // 控制汽车移动
    if (keyboardState[38]) {
      // 上箭头
      car.position.z -= 0.009;
      updateCamera();
    }
    if (keyboardState[40]) {
      // 下箭头
      car.position.z += 0.009;
      updateCamera();
    }
    if (keyboardState[37]) {
      // 左箭头
      car.rotation.y += 0.009;
      updateCamera();
    }
    if (keyboardState[39]) {
      // 右箭头
      car.rotation.y -= 0.009;
      updateCamera();
    }
    // 使用帧率器 监视帧率
    stats.update();

    renderer.render(scene, camera);
    // 使用轨道控制器
    controls.update();

    requestAnimationFrame(animate);
  };
  animate();
};

const updateCamera = () => {
  const distance = .5; // 调整这个距离以适应您的场景
  const yOffset = .2; // 调整垂直偏移量以将摄像机放置在汽车上方
  const target = car.position.clone(); // 将摄像机的目标设置为汽车的位置
  target.y += yOffset; // 将垂直偏移量添加到目标位置上

  // 根据汽车的位置和距离计算新的摄像机位置
  const offset = new THREE.Vector3(0, distance, -distance);
  const rotation = new THREE.Euler(-0.25, 0, 0, "XYZ"); // 根据需要调整旋转角度
  offset.applyEuler(rotation);
  const cameraPosition = target.clone().add(offset);

  // 设置摄像机位置并朝向汽车
  camera.position.copy(cameraPosition);
  camera.lookAt(target);
};

// 创建监听窗口大小变化的方法
const handleResize = () => {
  w.value = window.innerWidth;
  h.value = window.innerHeight;

  // camera
  camera.aspect = w.value / h.value;
  camera.updateProjectionMatrix();

  // Renderer
  renderer.setSize(w.value, h.value);
};
</script>

<template>
  <div id="container">
    <div id="three-container"></div>
    <div class="header">
      <b style="color: aliceblue; font-size: 3em">智能工厂</b>
    </div>
    <div class="left">
      <div>
        <ChartBar key="chart1" />
      </div>
      <div>
        <ChartBar key="chart2" />
      </div>
    </div>
    <div class="right">
      <div>
        <ChartBar key="chart3" />
      </div>
      <div>
        <ChartBar key="chart4" />
      </div>
    </div>
    <div class="footer"></div>
  </div>
</template>

<style lang="scss" scoped>
#container {
  position: relative;
  width: 100%;
  height: 100%;
}
#three-container {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.header {
  position: absolute;
  height: 80px;
  width: 100%;
  background: rgba(0, 0, 0, 0.6);
  display: flex;
  justify-content: center;
  align-items: center;
}
.left,
.right {
  position: absolute;
  height: 80%;
  width: 20%;
  top: 50%;
  transform: translateY(-45%);
  display: flex;
  flex-direction: column;

  &.left,
  &.right {
    & > :nth-of-type(1),
    & > :nth-of-type(2) {
      flex: 1;
      background: rgba(0, 0, 0, 0.6);
      border-radius: 18px;
    }
    & > :nth-of-type(1) {
      margin-bottom: 20px;
    }
  }
  &.left {
    left: 10px;
  }
  &.right {
    right: 10px;
  }
}

.footer {
}
</style>
